package serverWebApi;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import theaters.TheatersManager;
import theaters.TheatersManagerConfiguration;
import utilities.JsonUtils;
import utilities.XmlUtils;
import webApiEntities.Requests.BasicRequestMessage;
import webApiEntities.Requests.IRequestMessage;
import webApiEntities.Requests.MovieRequestMessage;
import webApiEntities.Requests.RequestClassAdapter;
import webApiEntities.Responses.BasicResponseMessage;
import webApiEntities.Responses.IResponseMessage;
import webApiEntities.Responses.MovieResponseMessage;
import webApiEntities.Responses.ResponseClassAdapter;
import webApiEntities.Responses.ShowResponseMessage;
import webApiEntities.Responses.TheaterResponseMessage;
import bl.EntityManager;
import entities.Entity;
import entities.Movie;
import entities.Show;
import entities.Theater;

/**
 * Servlet implementation class server
 */
@WebServlet("/server")
public class server extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private static final String CONTENT_TYPE = "application/json; charset=UTF-8";

	private EntityManager _moviemeBL;

	private static Logger _logger;

	private Timer _timer;

	private TimerTask _updatesMoviesDB;

	private TheatersManager _theatersManager;

	private static String _configFilePath;
	
	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		_configFilePath = servletConfig.getInitParameter("configPath");
	}
	
	/**
	 * @throws Exception 
	 * @see HttpServlet#HttpServlet()
	 */
	public server() throws Exception {
		super();

		_logger = Logger.getLogger(server.class);
		
		_logger.debug(_configFilePath);
		
		TheatersManagerConfiguration config = loadConfiguration("C:\\Program Files\\Akol\\MovieMe\\Config.xml");
		
		_theatersManager = new TheatersManager(config, _logger);

		_moviemeBL = EntityManager.getInstance();

		_updatesMoviesDB = new TimerTask() {

			@Override
			public void run() {
				// VLN: use the scripts of ABOUDI to updates the movies' data
				try {
					_logger.info("Adding movies...");

					List<Movie> movies = _theatersManager.getMovies();

					_logger.info("num of movies: " + movies.size());

					for(Movie movie: movies)
					{
						_logger.debug(movie.getMovieName());

						_moviemeBL.add(movie);
					}
				} catch (Exception e) {
					_logger.error("Cannot get movies from cinemacity. Exception: "+e);
				}


			}
		};
		
		_timer = new Timer("quick-movie");

		_timer.schedule(_updatesMoviesDB, 5*1000);

		_logger.info("The server is up!");
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// VLN: use get methods just for tests.
		try {
			String userRequestType = request.getParameter("user_request_type");

			IResponseMessage searchResult;

			switch (userRequestType) {
			case "Movies":
			{
				ArrayList<Entity> movies = new ArrayList<Entity>();

				movies.addAll(_moviemeBL.getAll(Movie.class));

				searchResult = new MovieResponseMessage(movies);

				break;
			}
			case "Shows":
			{
				ArrayList<Entity> shows = new ArrayList<Entity>();

				shows.addAll(_moviemeBL.getAll(Show.class));

				searchResult = new ShowResponseMessage(shows);

				break;
			}
			case "Theaters":
			{
				ArrayList<Entity> theaters = new ArrayList<Entity>();

				theaters.addAll(_moviemeBL.getAll(Theater.class));

				searchResult = new TheaterResponseMessage(theaters);

				break;
			}
			default:
			{
				//String userRequest = "{\"Requested\":\"Movie\",\"ByID\":[],\"ByObj\":[]}";
				BasicRequestMessage movieReMessage = new MovieRequestMessage(new ArrayList<Class<?>>(), new ArrayList<ArrayList<Entity>>());

				String userRequest = JsonUtils.toJson(movieReMessage, BasicRequestMessage.class, new RequestClassAdapter());

				IRequestMessage requestMessage = JsonUtils.fromJson(userRequest, BasicRequestMessage.class, new RequestClassAdapter());

				searchResult = requestMessage.HandleRequest();
				break;
			}
			}

			String result = JsonUtils.toJson(searchResult, BasicResponseMessage.class, new ResponseClassAdapter());

			response.setContentType(CONTENT_TYPE);
			response.getWriter().write(result);

		} catch (Exception e) {
			response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.toString());
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			String userRequest = request.getParameter("user_request");
			IRequestMessage requestMessage = JsonUtils.fromJson(userRequest, BasicRequestMessage.class, new RequestClassAdapter());
			IResponseMessage searchResult;

			searchResult = requestMessage.HandleRequest();

			String result = JsonUtils.toJson(searchResult, BasicResponseMessage.class, new ResponseClassAdapter());

			response.setContentType(CONTENT_TYPE);
			response.getWriter().write(result);
		} catch (Exception e) {
			response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.toString());
		}
	}
	
	private TheatersManagerConfiguration loadConfiguration(String configFilePath) throws Exception
	{
		return XmlUtils.read(TheatersManagerConfiguration.class, configFilePath);
	}
}
